package com.alm.handle.util;

import com.alm.handle.core.domain.entity.rs.ImgDataRS;
import com.alm.handle.core.domain.entity.vo.DevCronVo;
import com.alm.util.Misc;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import static com.alm.common.constant.Constants.COMMAND_MODEL;

/**
 * 命令、配置相关工具类
 * 前置知识：2位十六进制字符串 = 1字节
 *
 * @author 詹泽峰
 * @date 2024/07/05 16:26
 */
@Slf4j
public class DataUtils {

    /**
     * 包装命令
     *
     * @param mac         mac地址
     * @param devType     设备类型
     * @param commandType 命令类型
     * @param data        数据内容
     * @return java.lang.String
     * @author: 詹泽峰
     * @date: 2024/7/5 16:27
     */
    public static String setCommand(String mac, String devType, String commandType, String data) {
        //获取command模板
        StringBuffer cmd = new StringBuffer(COMMAND_MODEL);
        //替换命令类型
        DataUtils.replaceStr(cmd, "A5", commandType);
        //替换设备类型部分,有2处地方
        for (int i = 2; i > 0; i--) {
            DataUtils.replaceStr(cmd, "A3", devType);
        }
        //替换数据部分，如果为空则将数据区删除，数据区字节数置0
        if (StringUtils.isNotBlank(data)) {
            DataUtils.replaceStr(cmd, "A7", data);
            //计算数据区字节数，替换数据长度部分
            int dataLen = data.length() / 2;
            DataUtils.replaceStr(cmd, "A6", Misc.int2hexStr2(dataLen));
        } else {
            DataUtils.deleteStr(cmd, "A7");
            DataUtils.replaceStr(cmd, "A6", Misc.int2hexStr2(0));
        }
        //计算数据包字节数
        int packageLen = (cmd.substring(cmd.indexOf("A4") + "A4".length()).length() - "0A".length()) / 2;
        DataUtils.replaceStr(cmd, "A4", Misc.int2hexStr2(packageLen));
        //计算总字节数
        int totalLen = (cmd.length() - "0A".length()) / 2;
        DataUtils.replaceStr(cmd, "A1", Misc.int2hexStr2(totalLen));
        //替换Mac地址部分
        DataUtils.replaceStr(cmd, "A2A2A2A2A2A2", mac);
        //日志输出包装的命令
        return cmd.toString();
    }

    /**
     * 定时任务数据包的拆分解析，拼装成对象
     * 前置知识：2位十六进制字符串 = 1字节
     * 需要优化
     *
     * @param data
     * @return java.lang.String
     * @author: 詹泽峰
     * @date: 2024/7/9 14:25
     */
    public static DevCronVo parseCronData(String data) {
        DevCronVo devCronVo = new DevCronVo();
        String cronData = data.substring(12).toUpperCase();
        //开始位置从C1后第一个字节开始
        int startIndex = 2;
        //参数C1：任务id 长度：2字节 Integer 需十六进制转十进制
        if (startIndex + 2 <= cronData.length() && "C1".equals(cronData.substring(0, 2))) {
            devCronVo.setCronId(Integer.parseInt(cronData.substring(startIndex, startIndex + 4), 16));
            startIndex += 4;
        }
        //参数C2：任务启动日期（秒级时间戳） 长度：4字节 Long 需十六进制转十进制
        if (startIndex + 2 <= cronData.length() && "C2".equals(cronData.substring(startIndex, startIndex + 2))) {
            startIndex += 2;
            devCronVo.setCronStartDateTime(Long.parseLong(cronData.substring(startIndex, startIndex + 8), 16));
            startIndex += 8;
        }
        //参数C3：执行函数 长度：1字节 String
        if (startIndex + 2 <= cronData.length() && "C3".equals(cronData.substring(startIndex, startIndex + 2))) {
            startIndex += 2;
            devCronVo.setCronFunction(cronData.substring(startIndex, startIndex + 2));
            startIndex += 2;
        }
        //参数C4：变量1 长度：C4后的第一个字节表明后面跟多少字节 String
        if (startIndex + 2 <= cronData.length() && "C4".equals(cronData.substring(startIndex, startIndex + 2))) {
            startIndex += 2;
            int C4Len = Integer.parseInt(cronData.substring(startIndex, startIndex + 2), 16);
            startIndex += 2;
            devCronVo.setCronParam(cronData.substring(startIndex, startIndex + C4Len * 2));
            startIndex += C4Len * 2;
        }
        //未来可能有C5：变量2
        if (startIndex + 2 <= cronData.length() && "C5".equals(cronData.substring(startIndex, startIndex + 2))) {
            startIndex += 2;
        }
        //参数C6：循环类型 长度：1字节 Integer(0：循环一次，1：无限循环，2：运行总时长)
        if (startIndex + 2 <= cronData.length() && "C6".equals(cronData.substring(startIndex, startIndex + 2))) {
            startIndex += 2;
            devCronVo.setCycleType(Integer.parseInt(cronData.substring(startIndex, startIndex + 2), 16));
            startIndex += 2;
        }
        //参数C7：任务结束日期（秒级时间戳） 长度：4字节 Long 需十六进制转十进制
        if (startIndex + 2 <= cronData.length() && "C7".equals(cronData.substring(startIndex, startIndex + 2))) {
            startIndex += 2;
            devCronVo.setCronEndDateTime(Long.parseLong(cronData.substring(startIndex, startIndex + 8), 16));
            startIndex += 8;
        }
        //参数C8：循环间隔（默认1天，秒级时间戳） 长度：4字节 Long 需十六进制转十进制
        if (startIndex + 2 <= cronData.length() && "C8".equals(cronData.substring(startIndex, startIndex + 2))) {
            startIndex += 2;
            devCronVo.setCycleInterval(Integer.parseInt(cronData.substring(startIndex, startIndex + 8), 16));
            startIndex += 8;
        }
        //参数C9：任务启动状态 长度：1字节 Integer(0：启用，1：禁用)
        if (startIndex + 2 <= cronData.length() && "C9".equals(cronData.substring(startIndex, startIndex + 2))) {
            startIndex += 2;
            devCronVo.setCronSwitch(Integer.parseInt(cronData.substring(startIndex, startIndex + 2), 16));
            startIndex += 2;
        }
        //参数D1：任务执行状态 长度：1字节 Integer（0：运行中，1：暂停）
        if (startIndex + 2 <= cronData.length() && "D1".equals(cronData.substring(startIndex, startIndex + 2))) {
            startIndex += 2;
            devCronVo.setCronStatus((Integer.parseInt(cronData.substring(startIndex, startIndex + 2), 16)));
            startIndex += 2;
        }
        //参数D2：任务执行次数 长度：2字节 Integer（0：运行中，1：暂停）
        if (startIndex + 2 <= cronData.length() && "D2".equals(cronData.substring(startIndex, startIndex + 2))) {
            startIndex += 2;
            devCronVo.setCronStatus((Integer.parseInt(cronData.substring(startIndex, startIndex + 2), 16)));
            startIndex += 2;
        }
        //参数D3：任务每日结束时间 长度：1字节 Integer(0：循环一次，1：无限循环，2：运行总时长)
        if (startIndex + 2 <= cronData.length() && "D3".equals(cronData.substring(startIndex, startIndex + 2))) {
            startIndex += 2;
            devCronVo.setCronNextStartTime(Long.parseLong(cronData.substring(startIndex, startIndex + 8), 16));
            startIndex += 8;
        }
        return devCronVo;
    }

    /**
     * 解析异常信息
     *
     * @param exData data区
     * @return java.lang.String 异常信息
     */
    public static String parseDevExData(String exData) {
        /*
         * 掉电
         */
        int startIndex = 12;
        //获取B5（瞬时电压）部分的长度
        int b5Len = Integer.parseInt(exData.substring(startIndex, startIndex + 2));
        startIndex += 2;
        log.info("exData.substring: {}", exData.substring(startIndex, startIndex + 2));
        //若B5长度为0，或实际data区无数据，或实际数据区开头没有传B5参数，返回false，表示不是掉电异常
        if (startIndex + 2 < exData.length() && "B5".equals(exData.substring(startIndex, startIndex + 2))) {
            //跳过B5区域
            startIndex += b5Len * 2;
            //获取B6（瞬时电流）部分的长度
            int b6Len = Integer.parseInt(exData.substring(startIndex, startIndex + 2));
            startIndex += 2;
            //若B5长度为0，或实际data区无数据，或实际数据区开头没有传B6参数，返回false，表示不是掉电异常
            if (startIndex + 2 < exData.length() && "B6".equals(exData.substring(startIndex, startIndex + 2))) {
                return "Power Fail";
            }
        }
        return "No Exception";
    }

    public static String processImgData(String imgData) {
        int startIndex = imgData.indexOf("*/");
        int endIndex = imgData.indexOf('}');
        imgData = imgData.trim();
        imgData = imgData.substring(startIndex + 2, endIndex);
        imgData = imgData.replaceAll("0X", "");
        imgData = imgData.replaceAll(",", "");
        imgData = imgData.trim();
        return imgData;
    }

    public static ImgDataRS parseImgDataFeedback(String dataFeedback) {
        ImgDataRS imgDataRS = new ImgDataRS();
        dataFeedback = dataFeedback.substring(12).toUpperCase();
        int startIndex = 0;
        if(startIndex + 2 <= dataFeedback.length()) {
            imgDataRS.setImgType(dataFeedback.substring(startIndex, startIndex + 2));
            startIndex += 2;
        }
        if(startIndex + 4 <= dataFeedback.length()) {
            imgDataRS.setCurrentPackNum(Misc.hexStr2Int(dataFeedback.substring(startIndex, startIndex + 4)));
            startIndex += 4;
        }
        if(startIndex + 2 <= dataFeedback.length()) {
            imgDataRS.setState(Misc.hexStr2Int(dataFeedback.substring(startIndex, startIndex + 2)));
        }
        return imgDataRS;
    }

    public static void appendCronData(StringBuffer data, String paramType, String param) {
        if (StringUtils.isNotBlank(param)) {
            data.append(paramType).append(param);
        }
    }

    public static void appendImgFirstData(StringBuffer data, int length, String param) {
        if (StringUtils.isNotBlank(param)) {
            for (int i = 0; i < (length * 2 - param.length()); i++) {
                data.append("0");
            }
            data.append(param);
        }
    }

    public static void replaceStr(StringBuffer cmd, String target, String str) {
        int startIndex = cmd.indexOf(target);
        cmd.replace(startIndex, startIndex + target.length(), str);
    }

    public static void deleteStr(StringBuffer cmd, String target) {
        int startIndex = cmd.indexOf(target);
        cmd.delete(startIndex, startIndex + target.length());
    }
}
